package com.logic.landseaserver.ws;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.logic.landseaserver.ws.request.AchieveDayFreezeEnergyReq;
import com.logic.landseaserver.ws.request.AddMeterToExpenseReq;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.glassfish.jersey.server.Uri;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.logic.common.enums.HttpCodeEnum;
import com.logic.common.exception.BusinessException;
import com.logic.common.util.CommonResult;
import com.logic.common.util.CommonResultMap;
import com.logic.common.util.QueryUtil;
import com.logic.landseaserver.domain.Expenses;
import com.logic.landseaserver.service.IExpensesService;
import com.logic.landseaserver.service.utils.ResetQueryUtil;
import com.logic.landseaserver.ws.dto.ExpensesDTO;
import com.logic.landseaserver.ws.dto.ReadMeterTimeDTO;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

@Path("/expenses")
@Api(value = "expenses")
public class ExpensesRest {
    private static Logger logger = LoggerFactory.getLogger(ExpensesRest.class);
    @Autowired
    private IExpensesService expensesServiceImpl;

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "Create a new expenses")
    public Response create(@ApiParam(value = "param", required = true) Expenses expenses) {
        CommonResultMap map = new CommonResultMap();
        try {
            int id = expensesServiceImpl.insert(expenses);
            expenses.setId(id);
            map.setData(expensesServiceImpl.getDTO(id));
            map.setResult(CommonResult.SUCCESS, "Create success");
        } catch (BusinessException e) {
            logger.error("create error.", e);
            map.setResult(e);
        } catch (Exception e) {
            logger.error("create error.", e);
            map.setResult(CommonResult.ERROR, e.getMessage());
        }
        return Response.status(HttpCodeEnum.OK.getCode()).entity(map).build();
    }


    @DELETE
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "logic delete expenses by set deleted")
    public Response logicDelete(@ApiParam(value = "param", required = true) @QueryParam("expensesId") String ids) {
        CommonResultMap map = new CommonResultMap();
        try {
            expensesServiceImpl.delete(ids);
            map.setResult(CommonResult.SUCCESS, "delete expenses");
        } catch (BusinessException e) {
            logger.error("logicDelete error.", e);
            map.setResult(e);
        } catch (Exception e) {
            logger.error("logicDelete error.", e);
            map.setResult(CommonResult.ERROR, e.getMessage());
        }
        return Response.status(HttpCodeEnum.OK.getCode()).entity(map).build();
    }

    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "edit expenses ")
    public Response update(@ApiParam(value = "param", required = true) Expenses expenses) {
        CommonResultMap map = new CommonResultMap();
        try {
            expensesServiceImpl.update(expenses);
            map.setResult(CommonResult.SUCCESS, "edit expenses");
        } catch (BusinessException e) {
            logger.error("update error.", e);
            map.setResult(e);
        } catch (Exception e) {
            logger.error("update error.", e);
            map.setResult(CommonResult.ERROR, e.getMessage());
        }
        return Response.status(HttpCodeEnum.OK.getCode()).entity(map).build();
    }


    @GET
    @Path("/detail/{expensesId}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "Get expenses by expenses id")
    public Response retrieveDTO(
            @ApiParam(value = "param", required = true) @PathParam("expensesId") Integer expensesId) {
        CommonResultMap map = new CommonResultMap();
        try {
            map.setData(expensesServiceImpl.getDTO(expensesId));
            map.setResult(CommonResult.SUCCESS);
        } catch (Exception e) {
            logger.error("retrieveDTO error.", e);
            map.setResult(CommonResult.ERROR, e.getMessage());
        }
        return Response.status(HttpCodeEnum.OK.getCode()).entity(map).build();
    }


    @POST
    @Path("/detail/list")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "list expensess")
    public Response listDTO(@ApiParam(value = "param", required = true) QueryUtil queryUtil) {
        CommonResultMap map = new CommonResultMap();
        List<ExpensesDTO> expensesList = null;
        try {
            queryUtil.getPagingTool().calculateStartIndex();
            ResetQueryUtil.reset(queryUtil);
            expensesList = expensesServiceImpl.queryDTO(queryUtil);
            Integer totalCount = queryUtil.getPagingTool().getTotalNum();
            map.setData(expensesList);
            map.setResultTotalCount(totalCount);
            map.setResult(CommonResult.SUCCESS);

        } catch (Exception e) {
            logger.error("listDTO error.", e);
            map.setResult(CommonResult.ERROR, e.getMessage());
        }
        return Response.status(HttpCodeEnum.OK.getCode()).entity(map).build();
    }

    @GET
    @Path("/template/download/{projectId}/{expenseType}")
    @Produces("application/vnd.ms-excel; charset=UTF-8")
    @Consumes(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "download template excel")
    public void download(@Context HttpServletResponse response,
                         @ApiParam(value = "param", required = true) @PathParam("projectId") Integer projectId,
                         @ApiParam(value = "param", required = true) @PathParam("expenseType") String expenseType) {

        expensesServiceImpl.downloadTemplate(response, projectId, expenseType);
    }

    @POST
    @Path("/importFee")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "transfer webank report", position = 4)
    public Response importFee(@ApiParam(value = "file", required = true) @FormDataParam("file") InputStream file) throws Exception {
        CommonResultMap map = new CommonResultMap();
        try {
            ReadMeterTimeDTO readMeterTimeDTO = expensesServiceImpl.importFee(file);
            map.setData(readMeterTimeDTO);
            map.setResult(CommonResult.SUCCESS, "抄表读数导入成功");
        } catch (BusinessException e) {
            logger.error("抄表读数导入失败", e);
            map.setResult(CommonResult.BUSINESS_EXCEPTION, e.getMessage());
        } catch (Exception e) {
            logger.error("抄表读数导入失败", e);
            map.setResult(CommonResult.ERROR, e.getMessage());
        }
        return Response.status(HttpCodeEnum.OK.getCode()).entity(map).build();
    }

    @POST
    @Path("/createMonthFormEx")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "测试expenses表的数据自动生成账单", position = 5)
    public Response createMonthFormEx() {
        CommonResultMap map = new CommonResultMap();
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            expensesServiceImpl.batchInertMonthly();
            result.put("STATUS", 0);
            map.setData(result);
        } catch (Exception e) {
            logger.info("createMonthFormEx Exception", e);
            map.setResult(CommonResult.BUSINESS_EXCEPTION, e.getMessage());
        }
        return Response.status(HttpCodeEnum.OK.getCode()).entity(map).build();
    }

    @DELETE
    @Path("/clearExpenses")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "清除历史（三个月前）的运营数据", position = 5)
    public Response clearExpenses() {
        CommonResultMap map = new CommonResultMap();
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            expensesServiceImpl.backupexpenses();
            map.setResult(CommonResult.SUCCESS, "清除");
        } catch (Exception e) {
            logger.info("createMonthFormEx Exception", e);
            map.setResult(CommonResult.BUSINESS_EXCEPTION, e.getMessage());
        }
        return Response.status(HttpCodeEnum.OK.getCode()).entity(map).build();
    }


    @POST
    @Path("/batchInsertDingxinDate")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "从鼎信表导入到运营表")
    public Response test(@ApiParam(value = "param", required = true) String date) {
        CommonResultMap map = new CommonResultMap();
        try {
            expensesServiceImpl.batchInsertDingxinDate(date);
            map.setResult(CommonResult.SUCCESS, "Create success");
        } catch (Exception e) {
            logger.error("create error.", e);
            map.setResult(CommonResult.ERROR, e.getMessage());
        }
        return Response.status(HttpCodeEnum.OK.getCode()).entity(map).build();
    }

    @POST
    @Path("/batchInsertDingxinDatePrj")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "从鼎信表导入到运营表指定项目")
    public Response batchInsertDingxinDate( @ApiParam(value = "param", required = true) AddMeterToExpenseReq req) {
        CommonResultMap map = new CommonResultMap();
        try {
            expensesServiceImpl.batchInsertDingxinDatePrj(req);
            map.setResult(CommonResult.SUCCESS, "Create success");
        } catch (Exception e) {
            logger.error("create error.", e);
            map.setResult(CommonResult.ERROR, e.getMessage());
        }
        return Response.status(HttpCodeEnum.OK.getCode()).entity(map).build();
    }
}
